﻿/*
 * 只有多参数MorePara，没有单参数设定SinglePara
 * 没有随机振动位置测定 RandomPositionTest
 * 也没有过零检测CrossZero
 * CrossZero是前一秒的FinalAlarm的同步数据
 */

using System;

using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using IIDS_Bridge.MACRO;
using Server;
using NLog;
using System.Linq;

namespace IIDS_Bridge
{
    public delegate void OnBootFileLoading();
    public delegate void OnDSPConnected();
    class DspControlThread
    {
        //public  SemaphoreSlim _semWaveStart=new SemaphoreSlim(0,1);//信号量，当找到二级告警时，才通知绘图
        public bool _FlagWaveOTDRGot = false;//信号量，当从下位机采集完数据时，才继续描点绘图
        Logger log = LogManager.GetCurrentClassLogger();
        static DspControlThread instance = new DspControlThread();

        public const int UNIT_ROW = 8;
        private const int DATA_VOLUME = TOTAL_TIMES * UNIT_ROW;
        private const int TOTAL_TIMES = 24;//识别算法一次传送15次的数据
        //private int[,] dataPast = new int[CFAR_Column, DATA_VOLUME];//保存每个振动点,过去15s的数据
        private int[] pastEndFlag = new int[CFAR_Column];//记录过去15次每个振动点的循环数组的结束位置
        private static int[] futureEndFlag = new int[CFAR_Column];//记录未来15次每个振动点的循环数组的结束位置
        private int[,] dataFuture = new int[CFAR_Column, DATA_VOLUME];//保存每个振动点,振动点未来15s的数据
        public bool start_recognize = true;//识别算法开关

        private float[] SPRT = new float[CFAR_Column];                         //每个位置的序贯概率比
        private double[] T = new double[CFAR_Column];                          //每一列的系数
        private float[] Pd = new float[CFAR_Column];                           //每一列的检测概率
        private double[] Pfa = new double[CFAR_Column];                        //每一位置的虚警率
        private float[] AlarmFrameAdd = new float[CFAR_Column];                //已出现振动的桢
        public int[] AlarmFirstClass = new int[AlarmClassLength];//用于定义一类报警的容量
        public int[] AlarmSecondClass = new int[AlarmClassLength];
        //CFAR的训练个数40
        private int N = 40;
        private RecoThread recoThread = RecoThread.Get();

        //FirstAlarmcount,一帧中一类报警的个数
        //SecondAlarmcount,一帧中二类报警的个数
        private int FirstAlarmcount = 0;
        private int SecondAlarmcount = 0;
        private DspControlThread()
        { }

        public static DspControlThread Get()
        {
            return instance;
        }

        //引用DSP函数类
        public DspFunction dF = new DspFunction();
        #region Dsp的地址

        /* DSP中 CFAR+CrossZero
         * AlarmCountAddr为报警数据个数的地址
         * FinalAlarmAddr为最终报警数据信息的地址
         * SecondSynFlagAddr为上位机和DSP的秒同步标志位地址
         */
        public const uint AlarmCountAddr = 0x40004;
        public const uint FinalAlarmAddr = 0x49608;
        public const uint SecondSynFlagAddr = 0x90001;

        //DSP中的新增加OS_CFAR_RatioArray和CA_CFAR_RatioArray地址
        public const uint CA_CFAR_RatioArray_Addr = 0xA4000000;
        public const uint DSP_ROM_Addr = 0xB0000000;
       
        //DSP中的CFAR系数矩阵
        public float[] CA_CFAR_RatioArray = new float[CFAR_Column];


        #endregion

        #region 本程序变量
        public int AlarmC = 0;
        public int AlarmC_Mid = 0;

        /* 宏定义
         * finalAlarmC,用来存储最后报警信息
         * finalAlarmC_Mid，用来存储最后报警信息，做为中间变量来使用
         * AlarmClassLength，用来存储一类报警的长度。二类和一类报警长度相同。
         * CFAR_Column，DSP中二维CFAR矩阵的列数：Macro.CFAR_Column
         */
        //public int[] finalAlarmC = new int[Macro.MaxDSP_FinalAlarm_length];
        public int[] finalAlarm_all_data_otdr = new int[CFAR_Column];
        public int[] finalAlarmC_Mid = new int[Macro.MaxDSP_FinalAlarm_length];
        private const int AlarmClassLength = Macro.MaxAlarmClass_length;
        public const int CFAR_Column = Macro.CFAR_COLUMN;
        //public Mutex mut = new Mutex();

        //从Dsp传过来的IP和Port
        private string DSP_IP;
        private int DSP_PORT;

        //用于表示上位机和DSP的连接状态标志，false为断开，true为连接
        public static bool TCP_CONED = false;
        public static bool BOARD_CONNED = false;
        //用于表示本程序的主循环的是否结束，false为未结束，true为结束
        private bool ThreadIsEnd = false;


        public List<int>[] list_otdr_history_arr = new List<int>[CFAR_Column];

        #endregion

        #region 本类的属性

        /// <summary>
        /// 获取或者设置第一类报警的数目
        /// </summary>


        /// <summary>
        /// 获取或者设置第二类报警的数目
        /// </summary>

        #endregion

        #region 本类的方法

        public void WaveCollectOTDRInit()
        {
            this._FlagWaveOTDRGot = false;

        }
        public void ListOtdrInit()
        {
            for (int i = 0; i < CFAR_Column; i++)
            {
                if (list_otdr_history_arr[i] != null)
                    list_otdr_history_arr[i].Clear();
                else list_otdr_history_arr[i] = new List<int>();
            }

        }

        /// <summary>
        /// 方法：将DSP的IP和PORT端口从配置文件传递过来
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        public void GetIPandPoint(string ip, int port)
        {
            //将配置文件里的ip传递给本程序使用
            this.DSP_IP = ip;

            //将配置文件里的port传递给本程序使用
            this.DSP_PORT = port;
        }



        /// <summary>
        /// 方法：调用此方法将结束循环，终止本线程
        /// </summary>
        public void EndThread()
        {
            ThreadIsEnd = true;
        }

        /// <summary>
        /// 方法：返回和DSP的连接状态
        /// </summary>
        /// <returns></returns>
        public bool Connected()
        {
            return TCP_CONED;
        }

        /// <summary>
        /// 方法：给DSP加载更新文件
        /// </summary>

        /// <summary>
        /// 方法：通过传递TCP连接状态，触发事件，更改在界面上的显示状态
        /// </summary>
        /// <param name="state"></param>
        public void GetCotState(bool state)
        {
            //如果上次的连接状态和这次的连接状态不一样
            if (state != TCP_CONED)
            {
                TCP_CONED = state;
                //调用触发事件的方法
                OnStateChange(new StateEventArgs(TCP_CONED));
            }
            if (state == false) GetBoardState(false);
        }

        /// <summary>
        /// 方法：传递打开板卡成功与否的信息
        /// </summary>
        public bool GetBoardState(bool state) {
            BOARD_CONNED = state;
            return BOARD_CONNED;
        }
        #endregion

        #region 本类的事件触发类

        //改写继承自EventArgs的显示图像变化的参数类
        public class StateEventArgs : EventArgs
        {
            //定义传递的连接状态
            public readonly bool Connected;

            //有参数的构造函数
            public StateEventArgs(bool connected)
            {
                this.Connected = connected;
            }
        }

        //定义了一个StateEventArgs的事件
        public event EventHandler<StateEventArgs> StateChanged;

        /// <summary>
        /// 方法：判断已经定义的事件是否被订阅，若订阅则触发事件
        /// </summary>
        /// <param name="e"></param>
        public void OnStateChange(StateEventArgs e)
        {
            //判断一个事件是否被订阅
            if (StateChanged != null)
            {
                StateChanged(this, e);
            }
        }

        #endregion

        //给DSP下载文件的标志，0标示没开始下载或没下载成功，1表示下载成功



        //dowork函数
        public void dowork()
        {
            ListOtdrInit();
            //循环是否结束
            while (!ThreadIsEnd)
            {
                //判断有没有和PowerPC_DSP的socket通信是否已经建立连接
                if (dF.client != null)
                {
                    //若建立连接，则界面显示成功
                    GetCotState(dF.client.Connected);
                }
                else
                {
                    //如果没有建立连接界面显示失败

                    GetCotState(false);
                }

                //判断和PowerPC_DSP的socket的连接状态是否为真
               // if (!BOARD_CONNED)
                if(false)
                {
                    //若为假，则和PowerPC_DSP连接失败，进行与PowerPC_DSP连接
                    PowePC_DSPInit();
                }
                else
                {
                    //若为真，则和PowerPC_DSP连接成功，进行读写数据
                    ReadDataFromDSP();
                }
            }
        }

        /// <summary>
        /// 方法：和DSP连接状态为真，从DSP中读取报警数据
        /// </summary>
        int countTimes = 0;
        const int Cycle_Break = 8, Cycle_OTDR = 4;
        public bool start_detect = false;
        int temp_count_right = 0;
        private void ReadDataFromDSP()
        {
            if (!start_detect)
            {
                if (dF.client==null ||(dF.client!=null &&!dF.client.Connected) ) {
                    
                    Thread.Sleep(100);
                    return;
                }
                //int otdr_dlength = Macro.CFAR_COLUMN;
                //int[] OTDR_ALARM = new int[otdr_dlength];
                //if (!dF.DevReadOTDR(0, ref OTDR_ALARM, otdr_dlength))
                //{
                //    //Console.WriteLine("读取DSP OTDR数据错误");
                //    //dF.DevReOpen(0);
                //    //return;
                //}
                //OTDR_ALARM.CopyTo(MainForm.once_otdr_data, 0);
                ////storeIntToTxt(OTDR_ALARM, "D:\\otdr_decimal.txt");
                //_FlagWaveOTDRGot = true;
                ////Console.WriteLine("OtdrAlarm Length=" + otdr_dlength);

                //int alarm_dLength = 0;
                //int[] FinalAlarm = null;
                //if (!dF.DevReadAlarm(0, ref FinalAlarm, ref alarm_dLength))
                //{
                //    //临时注释
                //    //Console.WriteLine("读取DSP报警数据错误");
                //    //dF.DevReOpen(0);
                //    //return;
                //}

                //int alarm_Length = alarm_dLength / 3;//alarm length
                //Console.WriteLine("Fina|lAlarm Length=" + alarm_dLength);

            }
            //#region 从DSP中数据读取
            //二维CFAR矩阵矩阵中的报警事件的数目
            //二维CFAR矩阵矩阵中的报警事件的最后报警信息，是AlarmCount存储长度的3倍：     FinalAlarm - AlarmData
            if (start_detect) {
                DateTime start = DateTime.Now;
                countTimes = (countTimes + 1) % Cycle_Break;
                int[] FinalAlarm = null;// new int[Macro.CFAR_Column * Macro.CFAR_Row];  //最后报警的数组长度8000 * 3 
                Thread.Sleep(20);

                int alarm_dLength = 0;
                if (!dF.DevReadAlarm(0, ref FinalAlarm, ref alarm_dLength))
                {
                    //临时注释
                    //Console.WriteLine("读取DSP报警数据错误");
                    //dF.DevReOpen(0);
                    //return;
                }

                int alarm_Length = alarm_dLength / 3;//alarm length
                Console.WriteLine("Fina|lAlarm Length=" + alarm_dLength);

                //二维CFAR矩阵矩阵中的满足过零检测条件的列的数目
                int[] CrossZeroCount = new int[1];
                //二维CFAR矩阵矩阵中的满足过零检测条件的信息：列和过零率
                int[] FinalCrossZeroNum = new int[CFAR_Column * 2];
                //二维CFAR矩阵矩阵中的报警事件的数目
                int[] AlarmCount = new int[1];
                //二维CFAR矩阵矩阵中的报警事件的最后报警信息，是AlarmCount存储长度的3倍：     FinalAlarm - AlarmData
                float[] LR = new float[CFAR_Column];                         //每一个位置的似然比
                                                                             //用于存储二维CFAR矩阵每一列的对应的序贯信噪比,就是一次告警中，历史振幅的加权平均值
                int[] SNR_AVR = new int[CFAR_Column];
                //int[] SNR_AVR = new int[CFAR_Column];
                //用于存储二维CFAR矩阵中每一列的振动点个数
                int[] CFAR_OUT_NUM = new int[CFAR_Column];
                //int[] CFAR_OUT_SUM = new int[CFAR_Column]; //统计每一帧中每一列的有震动点的个数
                float LR_Delta;
                //系统设定的虚警率Alpha、误警率Beta
                float Alpha = (1f / 24f) / (3600f * 80f);
                float Beta = 0.1f;

                //序贯概率比中的高、低门限及最高限制门限
                float SPRT_TH1 = (float)Math.Log((Beta) / (1 - Alpha));
                float SPRT_TH2 = (float)Math.Log((1 - Beta) / Alpha);
                float SPRT_HIGH_LIMIT = SPRT_TH2 * 2;
                float LR_TH = 57f;
                Thread.Sleep(150);
                //三个一组归类数据
                //int temp_last_column = 0;

                temp_count_right++;
                List<Alarm> listSPRT = new List<Alarm>();
                for (int i = 0; i < alarm_Length; i++)
                {
                    Alarm alarm = new Alarm();
                    if (FinalAlarm[3 * i] > 20000 && FinalAlarm[3 * i + 2]<8000)
                    {
                        //错误顺序
                        Console.WriteLine("正确的次数为" + temp_count_right + "!!!!!!!!!!!!!!!!!!");
                        temp_count_right = 0;
                        alarm.column = FinalAlarm[3 * i + 2];
                        alarm.row = FinalAlarm[3 * i] % UNIT_ROW;
                        alarm.Amplitude = FinalAlarm[3 * i + 1];
                    }
                    else
                    {
                        //正常顺序
                        alarm.column = FinalAlarm[3 * i];
                        alarm.row = FinalAlarm[3 * i + 1] % UNIT_ROW;
                        alarm.Amplitude = FinalAlarm[3 * i + 2];
                    }
                 
                    listSPRT.Add(alarm);
                    //if (alarm.column != temp_last_column) Console.Write(alarm.column+" ");
                    //temp_last_column = alarm.column;
                    int col = alarm.column;
                    int row = alarm.row;
                    int borderStart = UNIT_ROW * countTimes;
                    if (futureEndFlag[col] > 0 && futureEndFlag[col] < DATA_VOLUME)
                    {
                        int futureRow = futureEndFlag[col] + row;
                        if (futureEndFlag[col] == 1)//说明这是第一次启动收集
                        {
                            futureRow = row;
                        }
                        dataFuture[col, futureRow] = alarm.Amplitude;
                    }
                }
                for (int tempi = 0; tempi < CFAR_Column; tempi++)
                {
                    if (futureEndFlag[tempi] > 0 && futureEndFlag[tempi] < DATA_VOLUME)
                    {
                        if (futureEndFlag[tempi] == 1)
                        {
                            futureEndFlag[tempi] = UNIT_ROW;
                            continue;
                        }
                        futureEndFlag[tempi] += UNIT_ROW;
                    }
                }
                //一类报警个数计数器
                int LR_ALARM_SUM = 0;
                //二类报警个数计数器
                int SPRT_ALARM_SUM = 0;

                //设定传输的报警点的个数为最大报警数，用宏定义//
                int Limit_Num = Macro.MaxAlarmCount;
                long Time = DateTime.Now.Ticks;

                //1ms为10000个计数周期，转换为以秒为单位
                Time = Time / 10000000;

                //移除一帧中列的位置重复的报警，未算入强度的平均值  ,开始进行KS校验
                int[] DuplicationFlag = new int[CFAR_Column];  //默认为0

                //开始进行SPRT检验
                
                foreach (Alarm al in listSPRT)
                {
                    //if (al.Amplitude > 500) Console.WriteLine(" 振动点位置 "+al.column+"+振幅  "+al.Amplitude +" CFAR次数"+al.row +"FinalAlarm"+ listSPRT.Count);
                    //KSFlag[Index] == 0 ，用于SPRT检验

                    int i = al.column;
                    //识别算法：本意用来限制进入识别的数量，最后这个参数没有用
                    // CFAR_OUT_NUM[ColumnInd] = CFAR_OUT_NUM[ColumnInd] + 1;
                    CFAR_OUT_NUM[i]++;

                    if (CFAR_OUT_NUM[i] >= 1) //-----------起始条件----------------------------------------
                    {
                        //若发生警报，则计算序贯概率比
                        Pd[i] = (float)Math.Pow((1 + T[i] / (1 + al.Amplitude)), -N);          //更新该列的Pd
                        LR_Delta = (float)Math.Log(Pd[i] / Pfa[i]);                                     //有振动的列需要增加的似然比
                        LR[i] = LR[i] + LR_Delta;                                                       //有振动的列的似然比的累加
                        SPRT[i] = SPRT[i] + LR_Delta;                                                   //有振动的列的序贯概率比的累加


                        if (SPRT[i] > SPRT_HIGH_LIMIT)
                        {
                            //SPRT不可无限累加，达到预定的值，就不再增加
                            SPRT[i] = SPRT_HIGH_LIMIT;
                        }
                    }
                    //如果是第一个警报则，则序贯信噪比=振幅
                    if (CFAR_OUT_NUM[i] == 1)
                    {
                        SNR_AVR[i] = al.Amplitude;
                    }
                    //如果是第二个警报以后，则序贯信噪比=[之前计算的序贯信噪比*（报警数量-1)+该点振幅]/报警数量；
                    else
                    {
                        SNR_AVR[i] = (al.Amplitude + SNR_AVR[i] * (CFAR_OUT_NUM[i] - 1)) / CFAR_OUT_NUM[i];
                    }
                }

                //遍历报警数目计数器（CFAR_OUT_NUM）的所有列（共2560列）
                for (int i = 0; i < CFAR_Column; i++)
                {
                    //判断每列报警个数是不是少于1
                    if (CFAR_OUT_NUM[i] < 1)
                    {
                        //若小于1，则将序贯概率比减少
                        SPRT[i] = SPRT[i] + (float)Math.Log(1 - Pd[i]);

                        //序贯概率比小于最小门限，则设为最低值
                        if (SPRT[i] <= SPRT_TH1)
                            SPRT[i] = (float)Math.Log(1d / (30 * 2d * 3600));

                        //连续报警帧减去1
                        AlarmFrameAdd[i] = AlarmFrameAdd[i] - 1;

                        //判断连续报警帧是否小于0
                        if (AlarmFrameAdd[i] < 0)
                        {
                            //若小于0，则置为0
                            AlarmFrameAdd[i] = 0;
                        }
                    }

                    //判断是否满足以下条件，一级报警提供数据
                    if (LR[i] > 0 && SNR_AVR[i] > 0)
                    {
                        AlarmFrameAdd[i] = AlarmFrameAdd[i] + 1;
                        AlarmFirstClass[LR_ALARM_SUM * 3] = 0;                         //行数：0
                        AlarmFirstClass[LR_ALARM_SUM * 3 + 1] = i;                     //列数：具体的列
                        AlarmFirstClass[LR_ALARM_SUM * 3 + 2] = SNR_AVR[i];            //信噪比平均值
                                                                                        //统计一级报警数目
                        LR_ALARM_SUM++;

                        //判断统计的一级报警数目是否大于设定值
                        if (LR_ALARM_SUM >= Limit_Num - 1)
                        {
                            //若大于，则设为最大的值
                            LR_ALARM_SUM = Limit_Num - 1;
                        }
                    }
                }
                //将统计的一级报警数据总和赋值给属性，供外部调用
                FirstAlarmcount = LR_ALARM_SUM;


                //遍历循环每列，进行二级报警数据选择
                for (int i = 0; i < CFAR_Column; i++)
                {
                    //数据量已经储备到数据量，启动算法
                    if (futureEndFlag[i] == DATA_VOLUME)
                    {
                        int[] dataFutureRow = new int[DATA_VOLUME];
                        for (int jj = 0; jj < DATA_VOLUME; jj++)
                        {
                            dataFutureRow[jj] = dataFuture[i, jj];
                        }
                        int amp_variance = (int)calcVariance(dataFutureRow);
                        int max_amplitude = (int)calcMax(dataFutureRow);
                        //RecoMsg recoMsg = new RecoMsg(ReConstructDataRow(dataFutureRow,DATA_VOLUME-1), i, avg_amplitude, DateTime.Now.AddSeconds(-5));
                        DateTime time_ll = DateTime.Now;
                        DateTime time_now = DateTime.Now.AddSeconds(-4);
                        //log.Debug(string.Format("{0}({1})进入识别队列时间{2}", i,i*16, time_now));
                        RecoMsg recoMsg = new RecoMsg(dataFutureRow, i, amp_variance, max_amplitude, time_now);
                        Thread.Sleep(20);
                        recoThread.Enqueue(recoMsg);
                        //wait_recoThread_count--;
                        continue;
                    }
                    //判断是否满足以下条件
                    if (SPRT[i] > SPRT_TH2 && LR[i] > LR_TH && AlarmFrameAdd[i] > 3 && SNR_AVR[i] > 0 && CFAR_OUT_NUM[i] > 0) //10-09 20:42,WYJ,
                    {
                        //若满足，则记录行数列数，信噪比
                        AlarmFrameAdd[i] = 3;
                        AlarmSecondClass[SPRT_ALARM_SUM * 3] = 0;                      //行数：0
                        AlarmSecondClass[SPRT_ALARM_SUM * 3 + 1] = i;                  //列数：具体的列
                        AlarmSecondClass[SPRT_ALARM_SUM * 3 + 2] = SNR_AVR[i];         //信噪比平均值
                                                                                        //若满足，则记录行数列数，信噪比
                        AlarmFrameAdd[i] = 3;

                        //统计二级报警数目
                        SPRT_ALARM_SUM++;

                        //判断统计的二级报警数目是否大于设定值,二级告警最大只能是4096
                        if (SPRT_ALARM_SUM >= Limit_Num - 1)
                        {
                            SPRT_ALARM_SUM = Limit_Num - 1;
                        }

                        //if (start_recognize && wait_recoThread_count < MAX_WAIT_RECO_COUNT)
                        if (start_recognize)
                        {
                            ////识别算法:监测到二级告警，修改状态
                            //recoStatus[i] = recoStatus[i] == 0 ? 2 : (recoStatus[i] + 2);
                            //如果告状态高于指定值，
                            //if (recoStatus[i] >= STATUS_MAX)//15s完成后才可以启动recoStatus[i] >= STATUS_MAX
                            //{
                            if (futureEndFlag[i] == 0)
                            {
                                //wait_recoThread_count++;
                                uint index = Convert.ToUInt32(i);
                                DecreaseSampleCA(index);
                                Thread.Sleep(20);
                                futureEndFlag[i]++;//启动收集数据
                            }
                            //recoStatus[i] = -40;
                            //短时间内不要再次监测
                            //}
                        }
                    }
                }
               
            //将统计的二级报警数据总和赋值给属性，供外部调用
            SecondAlarmcount = SPRT_ALARM_SUM;
            if (countTimes % 10 == 0)
            {
                log.Debug(string.Format("total={0},firstAlarm={1},secondAlarm={2}", listSPRT.Count, FirstAlarmcount, SecondAlarmcount));
            }
    }
    DateTime end = DateTime.Now;
    //Console.WriteLine("interval={0}",end.Subtract(start).TotalMilliseconds);

               




            //读取全线OTDR数据
            //if (countTimes % Cycle_OTDR != 0) return;
            //Thread.Sleep(800);
            //int otdr_dlength = Macro.CFAR_Column;
            //int[] OTDR_ALARM = new int[otdr_dlength];
            //if (!dF.DevReadOTDR(0, ref OTDR_ALARM, otdr_dlength))
            //{
            //    //Console.WriteLine("读取DSP OTDR数据错误");
            //    //dF.DevReOpen(0);
            //    //return;
            //}
            //OTDR_ALARM.CopyTo(MainForm.once_otdr_data, 0);
            ////storeIntToTxt(OTDR_ALARM, "D:\\otdr_decimal.txt");
            //this._FlagWaveOTDRGot = true;
            //Console.WriteLine("OtdrAlarm Length=" + otdr_dlength);
            //////读取断纤数据
            //if (countTimes % Cycle_Break != 0) return;
            //Thread.Sleep(20);
            //int breakColumnAvg = 0;
            //int breakColumnMax = 0;
            //if (!dF.DevReadBreak(0, ref breakColumnAvg, ref breakColumnMax))
            //{
            //    Console.WriteLine("读取DSP 断纤数据错误");
            //    dF.DevReOpen(0);
            //    return;
            //}
            //Console.WriteLine("breakColumnAvg ={0},breakColumnMax={1}", breakColumnAvg, breakColumnMax);


            //#endregion
            //若成功，判断读取的报警个数是否大于0

            //若报警个数大于0，则打印报警个数
        }

        internal void DevTCP()
        {
            dF.DevTCP(0, DSP_IP, DSP_PORT);
        }

        //private void storeIntToTxt(int[] shuzu, string path)
        //{
        //    FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write);
        //    StreamWriter sw = new StreamWriter(fs);
        //    //开始写入
        //    sw.WriteLine();
        //    sw.WriteLine("------------------------------------------------------------------");
        //    sw.WriteLine(DateTime.Now.ToString());
        //    for (int i = 0; i < shuzu.Length; i++)
        //    {
        //        //for (int j = 0; j < 100; j++)
        //        //{
        //        sw.Write(shuzu[i] + " ");
        //        //}
        //    }
        //    //清空缓冲区
        //    sw.Flush();
        //    //关闭流  
        //    sw.Close();
        //}
        //计算该点一次数据的方差
        public double calcMax(int[] a)
        {
            return a.Max();
        }
        public double calcVariance(int[] a)
        {
            double var_sum = 0, n;
            double Var;
            double avrg = a.Average();
            n = a.Count<int>();
            foreach (int x in a)
            {
                var_sum += (x - avrg) * (x - avrg);
            }
            Var = var_sum / n;
            return Var;
        }
        public static void ClearArray(ref int[] arr)
        {
            for (int i = 0; i < arr.Length; i++) arr[i] = 0;
        }
        public bool DSPClose()
        {
            return dF.DevClose(0);
        }
        public bool DSPOpen()
        {
            return dF.DevOpen(0, DSP_IP, DSP_PORT);
        }

        public void WriteBreakThreshold()
        {
            uint value = 0x1F4;
            dF.DevWritSpecial(0, dF.NETCMD_SPECIAL_NAME_BREAK, value);
        }
        /*采样点门限降低操作  */
        public bool DecreaseSampleCA(uint index)
        {
            Console.WriteLine("DecreaseSampleCA {0}({1})", index, index*5);
            return true;
        }
        //Read_More_CAOS_Paralist
        public static void ResetEndFlag(int i)
        {
            futureEndFlag[i] = 0;
        }

        /*采样点门限降低操作  */
        public bool IncreaseSampleCA(uint index)
        {
            Console.WriteLine("IncreaseSampleCA {0}({1})", index, index * 5);
            return true;
        }


        public bool WriteCaArray(int[] Ca_Write_Array, int start_index)
        {
            //mut.WaitOne();
            int dataLength = Ca_Write_Array.Length;
            uint Addr = CA_CFAR_RatioArray_Addr + (uint)start_index * 4;
            uint[] tmp_CA_Write_Array = new uint[dataLength];

            for (int i = 0; i < dataLength; i++)
            {
                tmp_CA_Write_Array[i] = (uint)Ca_Write_Array[i];
            }
            bool ret = dF.DevWriteCA(0, Addr, tmp_CA_Write_Array, dataLength);
            //mut.ReleaseMutex();
            return ret;
        }
        //byte[] sendData = { 0x5a, 0x5a, 0x5a, 0x5a, 0x34, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69 }; //要发送的字节数组
        //TcpClient client = null;//TcpClient实例
        //NetworkStream stream = null;//网络流

        //public bool runTCP()
        //{
        //    if (client != null && client.Connected) { stream.Close(); client.Close(); }
        //    try
        //    {
        //        Console.WriteLine(string.Format("Connect TCP IP={0},PORT={1}", DSP_IP, DSP_PORT));
        //        client = new TcpClient(DSP_IP, DSP_PORT);//实例化TcpClient
        //        stream = client.GetStream();//获取网络流
        //    }
        //    catch (System.Exception ex)
        //    {
        //        Console.WriteLine("Timed Out, Server no response");//连接失败
        //        return false;
        //    }
        //    return true;
        //}
        /// <summary>
        /// 与PowerPC_DSP建立连接的方法，即PowePC_DSP的初始化过程
        /// </summary>
        private void PowePC_DSPInit()
        {
            //Thread.Sleep(TimeSpan.FromSeconds(3));
            ////Console.WriteLine("Try connecting DSP ...");
            ////打开板卡,是否成功
            //if (!dF.DevOpen(0, DSP_IP, DSP_PORT)) { GetBoardState(false); Console.WriteLine("打开板卡失败"); return; }
            ////if (!dF.DevReset(0)) { Console.WriteLine("复位板卡失败"); return; }
            ////if (!dF.DevBoot(0, "")) { Console.WriteLine("加载板卡程序失败"); return; }
            //GetBoardState(true);
            //GetCotState(true);
            //if (DspConnectionOKEvent != null)
            //    DspConnectionOKEvent();
            ////stream.Write(sendData, 0, sendData.Length);//将数据写入网络流
            ////stream.Flush();
        }

        public class Alarm
        {
            public int row;
            public int column;
            public int Amplitude;
        }
    }
}

